
/* Simple JavaScript Inheritance
 * By John Resig http://ejohn.org/
 * MIT Licensed.
 */
// Inspired by base2 and Prototype
(function(){
  var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;

  // The base Class implementation (does nothing)
  this.Class = function(){};
 
  // Create a new Class that inherits from this class
  Class.extend = function(prop) {
    var _super = this.prototype;
   
    // Instantiate a base class (but only create the instance,
    // don't run the init constructor)
    initializing = true;
    var prototype = new this();
    initializing = false;
   
    // Copy the properties over onto the new prototype
    for (var name in prop) {
      // Check if we're overwriting an existing function
      prototype[name] = typeof prop[name] == "function" &&
        typeof _super[name] == "function" && fnTest.test(prop[name]) ?
        (function(name, fn){
          return function() {
            var tmp = this._super;
           
            // Add a new ._super() method that is the same method
            // but on the super-class
            this._super = _super[name];
           
            // The method only need to be bound temporarily, so we
            // remove it when we're done executing
            var ret = fn.apply(this, arguments);       
            this._super = tmp;
           
            return ret;
          };
        })(name, prop[name]) :
        prop[name];
    }
   
    // The dummy class constructor
    function Class() {
      // All construction is actually done in the init method
      if ( !initializing && this.init )
        this.init.apply(this, arguments);
    }
   
    // Populate our constructed prototype object
    Class.prototype = prototype;
   
    // Enforce the constructor to be what we expect
    Class.constructor = Class;

    // And make this class extendable
    Class.extend = arguments.callee;
   
    return Class;
  };
})();

var menus = {
    topMenus: [],
    
    initialize: function() {
        for (var i in menus.topMenus)
            menus.topMenus[i].render();
    }
    
}

menus.BaseItem = Class.extend({

    init: function(config) {
        this.rendered = false;
        this.config = config || {};
        this.el = null;
        this.labelWrapEl = null;
        this.labelEl = null;
        this.imgEl = null;
        this.parent = null;
    },

    render: function() {
        if (this.rendered) return;
        this.rendered = true;
        
        this.el = document.createElement('div');
        this.el.className = 'item';
        if (this.config.hidden)
            this.el.className += ' hidden';

        if (this.config.label) {
            this.labelWrapEl = document.createElement('div');
            this.labelWrapEl.className = 'label';
        
            if (this.config.icon) {
                this.imgEl = document.createElement('img');
                this.imgEl.src = this.config.icon;
                this.labelWrapEl.appendChild(this.imgEl);
            }
        
            this.labelEl = document.createElement('span');
            this.labelEl.innerHTML = this.config.label;
            this.labelWrapEl.appendChild(this.labelEl);
        
            this.el.appendChild(this.labelWrapEl);
        }
        
        var me = this;
        if (this.config.action) {
            $(this.el).click(function() {
                me.config.action(me);
            });
        }
        
        $(this.el).hover(function() {
            $(me.el).toggleClass('hover');
        });

        if (this.parent)
            this.parent.appendChild(this.el);
    },
    
    destroy: function() {
        if (! this.rendered) return;
        if (this.el && this.parent)
            this.parent.removeChild(this.el);
        this.el = null;
        this.parent = null;
    },
    
    setParent: function(parent) {
        this.parent = parent;
    },
    
    setLabel: function(label) {
        this.config.label = label;
        if (this.rendered && this.labelEl)
            this.labelEl.innerHTML = label;
    },
    
    setIcon: function(src) {
        this.config.icon = src;
        if (this.rendered && this.imgEl)
            this.imgEl.src = src;
    },
    
    setVisible: function(vis) {
        vis = !vis;
        this.config.hidden = vis;
        if (this.rendered && this.el) {
            if (vis)
                $(this.el).removeClass('hidden');
            else
                $(this.el).addClass('hidden');
        }
    }
    
});

menus.BaseMenu = menus.BaseItem.extend({

    init: function(config) {
        this._super(config);
        this.items = [];
        var items = ((typeof(config) === 'object') && config.items) ? config.items : [];
        for (var i in items)
            this.addItem(items[i]);
    },
    
    render: function() {
        if (this.rendered) return;
        this._super();
        $(this.el).removeClass('item').addClass('menu');
        
        this.itemsEl = document.createElement('div');
        this.itemsEl.className = 'items';
        this.itemsEl.innerHTML = '';
        this.el.appendChild(this.itemsEl);
        
        var me = this;
        $(this.el).hover(function() {
            $(me.itemsEl).toggle();
        });
        
        for (var i in this.items)
            this.items[i].render();
    },
    
    destroy: function() {
        if (! this.rendered) return;
        for (var i = 0; i < this.items.length; i++)
            this.items[i].destroy();
        this.items = [];
        this._super();
    },
    
    addItem: function(item) {
        if (item == '-')
            item = new menus.MenuSeparator({});
        else if (! (item instanceof menus.BaseItem)) {
            switch (item.type) {
                case 'separator':
                    item = new menus.MenuSeparator(item);
                    break;
                case 'header':
                    item = new menus.MenuHeader(item);
                    break;
                case 'checkbox':
                    item = new menus.MenuCheckbox(item);
                    break;
                case 'flyout':
                    item = new menus.MenuFlyout(item);
                    break;
                default:
                    item = new menus.MenuAction(item);
            }
        }
        this.items.push(item);
        item.setParent(this);
        
        // Special handling for separators
        var lastSep = false;
        for (var i in this.items) {
            var item = this.items[i];
            if (item instanceof menus.MenuSeparator) {
                item.setVisible(false);
                if (lastSep !== false) lastSep = item;
            } else {
                if (lastSep) lastSep.setVisible(true);
                lastSep = null;
            }
        }
        
        if (this.rendered)
            item.render();
        return item;
    },
    
    removeItem: function(item) {
        for (var i = 0; i < this.items.length; i++) {
            if (this.items[i] === item) {
                this.items.splice(i, 1);
                if (this.rendered)
                    item.destroy();
                item.setParent(null);
                return true;
            }
        }
        return false;
    },
    
    appendChild: function(el) {
        this.itemsEl.appendChild(el);
    },
    
    removeChild: function(el) {
        this.itemsEl.removeChild(el);
    }
    
});

menus.Menu = menus.BaseMenu.extend({

    init: function(config) {
        this._super(config);
        menus.topMenus.push(this);
    },

    render: function() {
        if (this.rendered) return;
        this._super();
        overviewer.map.controls[google.maps.ControlPosition.TOP_RIGHT].push(this.el);
    }
    
});

menus.MenuSeparator = menus.BaseItem.extend({

    init: function(config) {
        this._super(config);
    },
    
    render: function() {
        if (this.rendered) return;
        this._super();
        var hr = document.createElement('hr');
        $(this.el).addClass('separator');
        this.el.appendChild(hr);
        $(this.el).unbind('mouseenter');
        $(this.el).unbind('mouseleave');
    }
    
});

menus.MenuHeader = menus.BaseItem.extend({

    init: function(config) {
        this._super(config);
    },
    
    render: function() {
        if (this.rendered) return;
        this._super();
        $(this.el).addClass('header');
        if (! this.config.action) {
            $(this.el).unbind('mouseenter');
            $(this.el).unbind('mouseleave');
        }
    }
    
});

menus.MenuAction = menus.BaseItem.extend({

    init: function(config) {
        this._super(config);
    },
    
    render: function() {
        if (this.rendered) return;
        this._super();
        $(this.el).addClass('action');
    }
    
});

menus.MenuFlyout = menus.BaseMenu.extend({

    init: function(config) {
        this._super(config);
    },
    
    render: function() {
        if (this.rendered) return;
        this._super();
        $(this.el).removeClass('menu').addClass('item').addClass('flyout');
    }
    
});

menus.MenuCheckbox = menus.BaseItem.extend({

    init: function(config) {
        this._super(config);
    },
    
    render: function() {
        if (this.rendered) return;
        this._super();
        $(this.el).addClass('checkbox');

        if (this.labelWrapEl) {
            var cb = document.createElement('input');
            cb.type = 'checkbox';
            cb.checked = false;
            this.labelWrapEl.insertBefore(cb, this.labelWrapEl.firstChild);
            var me = this;
            if (this.config.action) {
                $(this.el).click(function(e) {
                    if (e.target !== cb)
                        cb.checked = !cb.checked;
                    me.config.action(me, cb.checked);
                });
                if (this.config.checked) {
                    cb.checked = true;
                    this.config.action(this, true);
                }
            }
        }
    }
    
});
    
menus.createMapControls = overviewer.util.createMapControls;
overviewer.util.createMapControls = function() {
    menus.createMapControls();
    menus.initialize();
}
